﻿using Bentley.CifNET.LinearGeometry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CheccCoverplateCulvertAssemble.Tools
{
    internal class PointOfIntersection
    {
        /// 计算线串与mesh的交点，uor尺度  斜线取交点
        /// </summary>
        /// <param name="lStrEl">线串元素</param>
        /// <param name="meshData">网格</param>
        /// <returns>交点</returns>
        public static DPoint3d CalculateIntersections(LineStringElement lStrEl, PolyfaceHeader meshData)
        {
            if (lStrEl == null || meshData == null)
                return DPoint3d.Zero;
            List<DPoint3d> lStrPoints = GetLineStringElPoints(lStrEl);
            //算出路线上的点
            //线串投影到mesh，并计算交点
            CurveVector drapedCurve = meshData.DrapeLinestring(lStrPoints, DVector3d.FromXYZ(1.0, 1.0, 1.0));
            //CurveVector drapedCurve = meshData.DrapeLinestring(lStrPoints, DVector3d.FromXYZ(0, 0, 1.0));
            if (drapedCurve == null)
                return DPoint3d.Zero;
            List<DPoint3d> dpli = CurveIntersection(lStrEl.GetCurveVector(), drapedCurve);
            if (dpli.Count > 0)
            {
                return dpli[0];
            }
            else
            {
                return DPoint3d.Zero;
            }
        }


        private static List<DPoint3d> CurveIntersection(CurveVector curveA, CurveVector curveB)
        {
            //控制精度
            double s_tol = 0.1;
            List<DPoint3d> intersectPoints = new List<DPoint3d>();

            //计算线串与投影线的交点
            CurveVector intersectA = new CurveVector(CurveVector.BoundaryType.None);
            CurveVector intersectB = new CurveVector(CurveVector.BoundaryType.None);
            CurveCurve.IntersectionsXY(intersectA, intersectB, curveA, curveB);

            foreach (var prim in intersectA)
            {
                PartialCurveDetail detailA, detailB;
                CurveCurve.IsPartialCurveDetailPair(intersectA, intersectB, (uint)intersectA.IndexOf(prim), out detailA, out detailB);
                if (detailA.IsSingleFraction)
                {
                    DPoint3d pA, pB;
                    detailA.ParentCurve.FractionToPoint(detailA.Fraction0, out pA);
                    detailB.ParentCurve.FractionToPoint(detailB.Fraction0, out pB);
                    if (pA.Distance(pB) < s_tol)
                        intersectPoints.Add(pA);
                }
                else
                {
                    DPoint3d pA1, pA2, pB1, pB2;
                    detailA.ParentCurve.FractionToPoint(detailA.Fraction0, out pA1);
                    detailA.ParentCurve.FractionToPoint(detailA.Fraction1, out pA2);
                    detailB.ParentCurve.FractionToPoint(detailB.Fraction0, out pB1);
                    detailB.ParentCurve.FractionToPoint(detailB.Fraction1, out pB2);
                    double s = pA1.Distance(pB1);
                    if (pA1.Distance(pB1) < s_tol)
                        intersectPoints.Add(pA1);
                    s = pA2.Distance(pB2);

                    if (pA2.Distance(pB2) < s_tol)
                        intersectPoints.Add(pA2);
                }
            }

            return intersectPoints;
        }
        /// <summary>
        /// 获取线串元素上的点
        /// </summary>
        /// <param name="lStrEl"></param>
        /// <returns></returns>
        private static List<DPoint3d> GetLineStringElPoints(LineStringElement lStrEl)
        {
            List<DPoint3d> points = new List<DPoint3d>();

            CurveVector curve = lStrEl.GetCurveVector();
            curve.GetAt(0).TryGetLineString(points);
            return points;
        }

    }
}
